package com.yupi.yuaicodemother.core;

import com.yupi.yuaicodemother.ai.AiCodeGeneratorService;
import com.yupi.yuaicodemother.ai.AiCodeGeneratorServiceFactory;
import com.yupi.yuaicodemother.ai.model.HtmlCodeResult;
import com.yupi.yuaicodemother.ai.model.MultiFileCodeResult;
import com.yupi.yuaicodemother.core.parser.CodeParserExecutor;
import com.yupi.yuaicodemother.core.saver.CodeFileSaverExecutor;
import com.yupi.yuaicodemother.exception.BusinessException;
import com.yupi.yuaicodemother.exception.ErrorCode;
import com.yupi.yuaicodemother.model.enums.CodeGenTypeEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * AI 代码生成门面类（Facade）
 * 作用：统一封装 AI 代码生成与保存逻辑，对外提供简洁的 API
 * 特点：屏蔽底层实现细节，支持同步与流式两种调用方式
 */
@Service
@Slf4j
public class AiCodeGeneratorFacade {

    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;

    /**
     * 同步生成并保存代码
     * 根据传入的生成类型，调用对应 AI 服务生成代码并保存到本地目录
     *
     * @param userMessage     用户输入的提示词
     * @param codeGenTypeEnum 代码生成类型（如 HTML、MULTI_FILE）
     * @param appId           应用 ID，用于定位保存路径
     * @return 保存后的本地目录
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum, Long appId) {
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生成类型不能为空");
        }

        // 根据 appId 获取对应的 AI 服务实例（支持多租户或不同配置）
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);

        // 根据生成类型分发处理逻辑
        return switch (codeGenTypeEnum) {
            case HTML -> {
                // 生成 HTML 代码
                HtmlCodeResult result = aiCodeGeneratorService.generateHtmlCode(1, userMessage);
                // 保存到本地目录
                yield CodeFileSaverExecutor.executeSaver(result, CodeGenTypeEnum.HTML, appId);
            }
            case MULTI_FILE -> {
                // 生成多文件项目代码
                MultiFileCodeResult result = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                // 保存到本地目录
                yield CodeFileSaverExecutor.executeSaver(result, CodeGenTypeEnum.MULTI_FILE, appId);
            }
            default -> {
                String errorMessage = "不支持的生成类型：" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };
    }

    /**
     * 流式生成并保存代码
     * 支持逐步返回 AI 生成内容，并在流结束时统一保存完整代码
     *
     * @param userMessage     用户输入的提示词
     * @param codeGenTypeEnum 代码生成类型
     * @param appId           应用 ID
     * @return Flux<String> 流式返回的代码片段
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenTypeEnum, Long appId) {
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生成类型不能为空");
        }

        // 获取 AI 服务实例
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);

        // 根据类型选择流式生成逻辑
        return switch (codeGenTypeEnum) {
            case HTML -> {
                // 获取 HTML 流式代码
                Flux<String> codeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                // 处理并保存流式结果
                yield processCodeStream(codeStream, CodeGenTypeEnum.HTML, appId);
            }
            case MULTI_FILE -> {
                // 获取多文件项目流式代码
                Flux<String> codeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                // 处理并保存流式结果
                yield processCodeStream(codeStream, CodeGenTypeEnum.MULTI_FILE, appId);
            }
            default -> {
                String errorMessage = "不支持的生成类型：" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };
    }

    /**
     * 通用流式代码处理逻辑
     * 作用：收集所有流式片段，最终统一解析并保存为完整项目
     *
     * @param codeStream  流式代码片段
     * @param codeGenType 代码生成类型
     * @param appId       应用 ID
     * @return 原始流式片段（不做修改，直接透传）
     */
    private Flux<String> processCodeStream(Flux<String> codeStream, CodeGenTypeEnum codeGenType, Long appId) {
        // 用于拼接完整代码内容
        StringBuilder codeBuilder = new StringBuilder();

        return codeStream
                .doOnNext(chunk -> {
                    // 实时收集每一帧代码片段
                    codeBuilder.append(chunk);
                })
                .doOnComplete(() -> {
                    // 流结束后：解析并保存完整代码
                    try {
                        String completeCode = codeBuilder.toString();
                        // 使用代码解析器将字符串转为结构化对象（如 HTML 或项目结构）
                        Object parsedResult = CodeParserExecutor.executeParser(completeCode, codeGenType);
                        // 使用保存器将代码写入本地目录
                        File saveDir = CodeFileSaverExecutor.executeSaver(parsedResult, codeGenType, appId);
                        log.info("保存成功，目录为：{}", saveDir.getAbsolutePath());
                    } catch (Exception e) {
                        log.error("保存失败: {}", e.getMessage());
                    }
                });
    }
}